package edu.hubu.talentmanagementsystem.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.base.CaseFormat;
import edu.hubu.talentmanagementsystem.mapper.${modelClassName}Mapper;
import edu.hubu.talentmanagementsystem.mapper.context.MapperContext;
import edu.hubu.talentmanagementsystem.model.ext.${modelClassName};
import edu.hubu.talentmanagementsystem.service.I${modelClassName}Service;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import edu.hubu.talentmanagementsystem.common.EncodeOperation;
import edu.hubu.talentmanagementsystem.common.EncodeParam;

import java.util.List;
import java.util.Optional;

/**
 * @author moonlan
 * date 2021/3/2 下午8:45
 */
@SuppressWarnings(value = "unused")
@Service
@Transactional(rollbackFor = Exception.class)
public class ${modelClassName}ServiceImpl extends ServiceImpl<${modelClassName}Mapper, ${modelClassName}> implements I${modelClassName}Service {

    private final MapperContext context;

    public ${modelClassName}ServiceImpl(MapperContext context) {this.context = context;}

    @Override
    public boolean deleteById(Integer id) {
        return context.get${modelClassName}Mapper().deleteById(id) > 0;
    }

    @Override
    @EncodeOperation
    public Optional<${modelClassName}> insert(@EncodeParam ${modelClassName} record) {
        int insert = context.get${modelClassName}Mapper().insert(record);
        if (insert > 0) {
            return Optional.of(context.get${modelClassName}Mapper().selectById(record.primaryKeyValue()));
        }
        return Optional.empty();
    }

    @Override
    public Optional<${modelClassName}> selectById(Integer id) {
        QueryWrapper<${modelClassName}> wrapper = new QueryWrapper<>();
        LambdaQueryWrapper<${modelClassName}> lambdaQueryWrapper = getColumnWrapper(wrapper.lambda()).eq(${modelClassName}::get${modelClassName}Id, id);
        return Optional.of(context.get${modelClassName}Mapper().selectOne(lambdaQueryWrapper));
    }

    @Override
    public List<${modelClassName}> selectAll(String order) {
        QueryWrapper<${modelClassName}> wrapper = new QueryWrapper<>();
        if (!StringUtils.hasText(order)) {
            LambdaQueryWrapper<${modelClassName}> select = getColumnWrapper(wrapper.lambda());
            return context.get${modelClassName}Mapper().selectList(select);
        }
        wrapper.orderByAsc(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, order));
        LambdaQueryWrapper<${modelClassName}> select = getColumnWrapper(wrapper.lambda());
        return context.get${modelClassName}Mapper().selectList(select);
    }

    @Override
    public Page<${modelClassName}> selectAllPaged( Integer currentPage,
             Integer pageSize, String order) {
        QueryWrapper<${modelClassName}> wrapper = new QueryWrapper<>();
        Page<${modelClassName}> page = new Page<>(currentPage, pageSize);
        if (!StringUtils.hasText(order)) {
            LambdaQueryWrapper<${modelClassName}> select = getColumnWrapper(wrapper.lambda());
            return context.get${modelClassName}Mapper().selectPage(page, select);
        }
        wrapper.orderByAsc(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, order));
        LambdaQueryWrapper<${modelClassName}> select = getColumnWrapper(wrapper.lambda());
        return context.get${modelClassName}Mapper().selectPage(page, select);
    }

    private LambdaQueryWrapper<${modelClassName}> getColumnWrapper(LambdaQueryWrapper<${modelClassName}> wrapper) {
        return wrapper.select(
            <#assign len = columns?size/>
            <#list columns as m>
                ${modelClassName}::${m}
                <#if m_index < len - 1>
                    ,
                </#if>
            </#list>
        );
    }

    @Override
    public Page<${modelClassName}> selectLikePaged( Integer currentPage,
             Integer pageSize, ${modelClassName} record, String order) {
        Page<${modelClassName}> page = new Page<>(currentPage, pageSize);
        QueryWrapper<${modelClassName}> wrapper = new QueryWrapper<>();
        if (!StringUtils.hasText(order)) {
            return context.get${modelClassName}Mapper().selectPage(page, getColumnWrapper(getQueryWrapper(wrapper, record)));
        }
        wrapper.orderByAsc(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, order));
        return context.get${modelClassName}Mapper().selectPage(page, getColumnWrapper(getQueryWrapper(wrapper, record)));
    }

    private LambdaQueryWrapper<${modelClassName}> getQueryWrapper(QueryWrapper<${modelClassName}>wrapper, ${modelClassName} record) {
        LambdaQueryWrapper<${modelClassName}> lambda = wrapper.lambda();
<#list methodsWithNotStringAndDate as m>
        if (record.${m}() != null) {
            lambda = lambda.eq(${modelClassName}::${m},record.${m}());
        }
</#list >
<#if hasMethodsWithString == true >
    <#list methodsWithString as m>
        if (record.${m}() != null) {
            lambda = lambda.like(${modelClassName}::${m},record.${m} ());
        }
    </#list >
</#if>
<#if hasMethodsWithDate == true >
    <#list methodsWithDate as m>
        if (record.${m}() != null) {
            lambda = lambda.eq(${modelClassName}::${m},record.${m} ())
        }
    </#list >
</#if>
        return lambda;
    }

    public int count(${modelClassName} record) {
        return context.get${modelClassName}Mapper().selectCount(getQueryWrapper(new QueryWrapper<>(), record));
    }

    @Override
    @EncodeOperation
    public Optional<${modelClassName}> updateById(Integer id, @EncodeParam ${modelClassName} record) {
        record.set${modelClassName}Id(id);
        int update = context.get${modelClassName}Mapper().updateById(record);
        if (update > 0) {
            QueryWrapper<${modelClassName}> wrapper = new QueryWrapper<>();
            LambdaQueryWrapper<${modelClassName}> lambdaQueryWrapper = getColumnWrapper(wrapper.lambda()).eq(${modelClassName}::get${modelClassName}Id, id);
            return Optional.of(context.get${modelClassName}Mapper().selectOne(getColumnWrapper(lambdaQueryWrapper)));
        }

        return Optional.empty();
    }
}
